// 由于JavaScript的函数可以嵌套，此时，内部函数可以访问外部函数定义的变量，反过来则不行：

function fc() {
    var a = 1
    console.log(a);

    function fcc() {
        var b = a + 1

        console.log(b);
    }
    fcc();
}

fc();


// 这说明JavaScript的函数在查找变量时从自身函数定义开始
// ，从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量，则内部函数的变量将“屏蔽”外部函数的变量

function fc() {
    var a = 1
    console.log(a);

    function fcc() {
        var a = 'A'
        var a = a + 1

        console.log(a);
    }
    fcc();
}

fc();

function abc() {
    var b = '我是熊大'
    var a = '我是' + '光头强'
    var b = a + b
    console.log(b);
    var b = '我是熊大'
    console.log(b);

}

abc();


// 不在任何函数内定义的变量就具有全局作用域
// 。实际上，JavaScript默认有一个全局对象window，全局作用域的变量实际上被绑定到window的一个属性：

function aa() {
    console.log('为什么最迷人的最危险');
}


window.aa();




// 你可能猜到了，由于函数定义有两种方式，以变量方式var foo = function () {}定义的函数实际上也是一个全局变量，
// 因此，顶层函数的定义也被视为一个全局变量，并绑定到window对象：
// console.log('现在alert还可以使用');
// alert('我是嫩爹')

// var oldalert = alert;


// alert = function() {
//     console.log('现在aler废了');
// }

// alert('abcdefg')
// console.log('alert没用了');

// alert = oldalert

// alert('我又好了。。。')



// 名字空间
// 全局变量会绑定到window上，不同的JavaScript文件如果使用了相同的全局变量，或者定义了相同名字的顶层函数，都会造成命名冲突，并且很难被发现。

// 减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。例如：
var x = {};
x.name = '哆啦A梦'
x.sex = '男'
x.dress = '饭都花园'


x.pronty = function() {
    console.log('我是x.nb里面的东西');

}



// 局部作用域
// 由于JavaScript的变量作用域实际上是函数内部，我们在for循环等语句块中是无法定义具有局部作用域的变量的：

'use strict';

function foo() {
    for (var i = 0; i < 10; i++) {
        console.log(i);
    }
    console.log(i);
}
foo()

// 为了解决块级作用域，ES6引入了新的关键字let，用let替代var可以申明一个块级作用域的变量：

function fooo() {
    var sum = 0;
    for (let i = 0; i < 10; i++) {
        console.log(i);
    }
    // 报错console.log(i);
}
fooo()


// 常量
// 由于var和let申明的是变量，如果要申明一个常量，在ES6之前是不行的，我们通常用全部大写的变量来表示“这是一个常量，不要修改它的值”：


// ES6标准引入了新的关键字const来定义常量，const与let都具有块级作用域：

'use strict';

const PI = 3; // 某些浏览器不报错，但是无效果！

console.log(PI + 'pi是');